import EventType from "../../model/EventType";
import Singleton from "../context/Singleton";
import EventManage from "../event/EventManage";
import UIConfig from "../config/UIConfig";
import UIManage from "../gui/UIManage";
import { Logger } from "../log/logger";
import Utils from "../utils/Utils";
import { getPos, pos } from "./PosDefine";
import SpineItem from "./SpineItem";

//骨骼动画工厂，自动清理动画内存
export default class SpineFactory extends Singleton {

    static get I() { return this.Instance() }

    private tempLateArr = new Map<number, Laya.Templet>();
    private keyH = new Laya.StringKey();

    //待销毁列表
    private desArr = new Set<number>();

    onInit() {
        Logger.logBusiness("spine初始化", "spine")
        EventManage.I.on(EventType.SK_DESTORY, this, this.onItemDestory);
        Laya.timer.loop(UIConfig.skDestoryTick, this, this.onTick);
    }

    /**
     * 创建骨骼动画
     * @param path 路径
     * @param caller 标识，方便批量释放
     * @returns 
     */
    create(path: string, caller: any = null): SpineItem {
        let item = SpineItem.create();
        item.sign = caller;
        this.createByPath(path, item)
        return item;
    }

    //播放特效，播放完成自动释放
    playSk(path: string, pos: pos, parent: Laya.Sprite = UIManage.Instance().effLayer) {
        let tem = getPos(pos, parent);
        this.create(path)
            .setP(parent, tem[0], tem[1])
            .play(0)
            .dispose();
    }

    /**
     * 
     * @param path 路径不传全部清理
     * @returns 
     */
    clear(path?: string) {
        let arr = this.tempLateArr;

        if (Utils.isNil(path)) {
            arr.forEach((v, k) => v.destroy());
            arr.clear();
            return;
        }

        let key = this.keyH.getID(path);
        if (arr.has(key)) {
            let item = arr.get(key);
            item.destroy();
            arr.delete(key);
        }
    }

    calerByCaller(sign?: any) {
        
    }

    //清理未引用动画
    clearUnuse() {
        let arr = this.tempLateArr;
        if (arr.size <= 0) return;

        arr.forEach((v, k) => {
            if (v.referenceCount <= 0) {
                v.destroy();
                arr.delete(k);
            }
        })
    }

    private onTick() {
        let arr = Array.from(this.desArr);
        this.desArr.clear();
        while (arr.length > 0) {
            let k = arr.pop();
            let elm = this.tempLateArr.get(k);
            if (!elm || elm.referenceCount > 0) continue;
            this.clear(this.keyH.getName(k))

        }
    }

    private onItemDestory(k) {

        let elm = this.tempLateArr.get(k);
        if (!Utils.isNil(elm) && elm.referenceCount <= 0) {
            this.desArr.add(k);
        }

        Logger.logBusiness(this.keyH.getName(k), "销毁动画:")
    }

    private onComplete(item: SpineItem, sk: Laya.Skeleton, path: number) {
        item.setScore(sk, path);
        item.setComplete();
    }

    private onErr(err: any) {
        Logger.logView(err);
    }

    private createByPath(path: string, item: SpineItem) {
        let arr = this.tempLateArr;
        let key = this.keyH.getID(path);

        if (arr.has(key)) {
            let sk = arr.get(key).buildArmature();
            this.onComplete(item, sk, key);
        } else {
            let elm = new Laya.Templet();
            let k = this.keyH.add(path);
            arr.set(k, elm);
            elm.on(Laya.Event.COMPLETE, this, () => void this.onComplete(item, elm.buildArmature(), k));
            elm.on(Laya.Event.ERROR, this, this.onErr);
            elm.loadAni(path);
        }
    }
}